<template>
    <div :class="float ? 'cec-anchor_float' : 'cec-anchor'" :style="{ height }">
        <div :class="`anchor-header ${float ? getHeaderPosition : ''}`">
            <div class="anchor-trunk" :style="{ height: getAnchorLinkHeight }">
                <div class="anchor-icon" ref="anchor-icon">
                    <div class="anchor-icon-white"></div>
                </div>
            </div>
            <div class="anchor-link" :style="{ height: getAnchorLinkHeight }">
                <AnchorLink :data="data" @goAnchor="goAnchor" :currentAnchor="currentAnchor"></AnchorLink>
            </div>
        </div>
        <div ref="anchor-body" class="anchor-body" @scroll="scrollEvent($event)">
            <slot></slot>
        </div>
    </div>
</template>
<script>
    import { prefixCls } from '../prefix'
    import AnchorLink from "./AnchorLink.vue";
    import './anchor.css'
    export default {
        name: `${prefixCls}Anchor`,
        props: {
            float: Boolean,
            placement: {
                type: String,
                default: "leftTop",
            },
            itemHeight: {
                type: Number,
                default: 30,
            },
            data: {
                type: Array,
                default: () => [],
            },
            height: {
                type: String,
                default: '',
            },
        },
        components: {
            AnchorLink,
        },
        computed: {
            //获取所有锚点组合的锚点高度
            getAnchorLinkHeight() {
                let childrenHeight = 0;
                this.data.forEach((ele) => {
                    if (ele.children && ele.children.length > 0) {
                        childrenHeight += ele.children.length * 30;
                    }
                });
                return childrenHeight + 30 * this.data.length - 20 + "px";
            },
            //获取所有锚点组合的位置
            getHeaderPosition() {
                switch (this.placement) {
                    case 'leftTop':
                        return 'placement-left-top';
                    case 'leftCenter':
                        return 'placement-left-center';
                    case 'leftBottom':
                        return 'placement-left-bottom';
                    case 'rightTop':
                        return 'placement-right-top';
                    case 'rightCenter':
                        return 'placement-right-center';
                    case 'rightBottom':
                        return 'placement-right-bottom';
                    default:
                        return '';
                }
            },
        },
        watch: {
            //监听数据变化，获取所有锚点（方便后面计算），获取第一个锚点的偏差
            //（因为offset计算的是当前容器被卷去的高度，可能你的高度存在偏差，所以需要减去）
            data: {
                handler(val) {
                    if (val && val.length > 0) {
                        this.allAnchor = this.getAllAnchor(val);
                        //偏差
                        this.$nextTick(() => {
                            var anchor = document.querySelector(val[0].tar);
                            if(!anchor) return
                            this.offset = anchor.offsetTop;
                        });
                    }
                },
                deep: true,
                immediate: true,
            },
        },
        data() {
            return {
                currentAnchor: '',
                oldHeight: 0,
                scorllTimer: null,
                allAnchor: [],
                offset: 0,
            };
        },
        mounted() {
            this.init()
        },
        methods: {
            //初始计算第一个锚点位置并定位
            init() {
                const { data } = this
                if(!data && !data.length) return
                const tar = data[0].tar
                this.goAnchor(tar)
            },
            emitAnchor(val) {
                this.$emit('on-change', val)
            },
            //递归获取所有锚点的值
            getAllAnchor(anchor) {
                let anchorTree = [];
                anchor.forEach((ele) => {
                    anchorTree.push({ tar: ele.tar, title: ele.title })
                    if (ele.children && ele.children.length > 0) {
                        anchorTree.push(...this.getAllAnchor(ele.children))
                    }
                });
                return anchorTree
            },
            //点击锚点滚动
            goAnchor(selector) {
                this.currentAnchor = selector;
                var anchor = document.querySelector(selector);
                if(!anchor) return
                let scorllHeight = anchor.offsetTop;
                let height = this.oldHeight;
                clearInterval(this.scorllTimer);
                //使用 定时器来模拟滚动 防止一下就滚动到指定位置
                //记得判断向上滚动还是下滚动
                if (scorllHeight > this.oldHeight) {
                    this.scorllTimer = setInterval(() => {
                        height = height + 50;
                        if (height >= scorllHeight) {
                            height = scorllHeight;
                            clearInterval(this.scorllTimer);
                            this.scorllTimer = null;
                        }
                        // 减去偏差，不然会错位
                        this.$refs['anchor-body'].scrollTop = height - this.offset;
                    }, 10);
                } else {
                    this.scorllTimer = setInterval(() => {
                        height = height - 50 - this.offset;
                        if (height <= scorllHeight) {
                            height = scorllHeight;
                            clearInterval(this.scorllTimer);
                            this.scorllTimer = null;
                        }
                        this.$refs['anchor-body'].scrollTop = height - this.offset;
                    });
                }

                //锚点前面的圆圈定位
                this.allAnchor.forEach((ele, i) => {
                    if (ele.tar === selector) {
                        this.$refs['anchor-icon'].style.display = "block";
                        this.$refs['anchor-icon'].style.top = i * 30 + 2 + "px";
                    }
                });
                this.oldHeight = scorllHeight;
            },
            //页面滚动， 判断当前的scrollTop在哪个锚点之间，修改锚点的样式
            scrollEvent() {
                if (this.scorllTimer != null) {
                    return;
                }
                //当前滚动位置
                let scrollTop = this.$refs['anchor-body'].scrollTop;
                this.allAnchor.forEach((ele, i) => {
                    let dom = document.querySelector(ele.tar);
                    if (dom) {
                        if (scrollTop > dom.offsetTop && scrollTop <= dom.offsetTop + dom.offsetHeight / 3) {
                            this.currentAnchor = ele.tar;
                            this.$refs['anchor-icon'].style.display = "block";
                            this.$refs['anchor-icon'].style.top = i * 30 + 2 + "px";
                            return;
                        }
                    }
                });
            },
        },
    };
</script>
